package com.liliudong.template.biz.service.sys.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liliudong.template.biz.mapper.sys.SysDictMapper;
import com.liliudong.template.biz.service.sys.SysDictItemService;
import com.liliudong.template.biz.service.sys.SysDictService;
import com.liliudong.template.common.constant.ExMessageEnum;
import com.liliudong.template.common.convert.sys.SysDictConvert;
import com.liliudong.template.common.convert.sys.SysDictItemConvert;
import com.liliudong.template.common.dto.sys.*;
import com.liliudong.template.common.entity.sys.SysDict;
import com.liliudong.template.common.entity.sys.SysDictItem;
import com.liliudong.template.common.exception.BizException;
import com.liliudong.template.common.vo.PageVO;
import com.liliudong.template.common.vo.sys.SysDictDetailVO;
import com.liliudong.template.common.vo.sys.SysDictListVO;
import com.liliudong.template.common.vo.sys.SysDictPageVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 系统-字典表 服务实现
 *
 * @author ldli5
 * @date 2024-07-04 14:57:52
 */
@Service
@RequiredArgsConstructor
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict>
		implements SysDictService {

	public static final String SYS_DICT_LIST_CACHE_KEY = "SYS:DICT:LIST";
	private final SysDictItemService sysDictItemService;

	private final StringRedisTemplate stringRedisTemplate;

	@Override
	@Transactional
	public void addOne(SysDictAddDTO sysDictAddDTO) {
		stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
		SysDict sysDict = SysDictConvert.INSTANCE.addDTO2Entity(sysDictAddDTO);
		this.save(sysDict);
		List<SysDictItemAddDTO> sysDictItemList = sysDictAddDTO.getSysDictItemList();
		if (CollUtil.isNotEmpty(sysDictItemList)) {
			List<SysDictItem> sysDictItems = SysDictItemConvert.INSTANCE.addDTOList2EntityList(sysDictItemList);
			sysDictItemService.saveBatchByDictId(sysDict.getId(), sysDictItems);
		}
	}

	@Override
	public void deleteById(Long id) {
		stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
		long count = sysDictItemService.countByDictId(id);
		if (count > 0) {
			throw new BizException(ExMessageEnum.DATA_OCCUPIED);
		}
		removeById(id);
	}

	@Override
	@Transactional
	public void modifyById(Long id, SysDictModifyDTO sysDictModifyDTO) {
		stringRedisTemplate.delete(SYS_DICT_LIST_CACHE_KEY);
		SysDict sysDict = SysDictConvert.INSTANCE.modifyDTO2Entity(sysDictModifyDTO);
		sysDict.setId(id);
		this.updateById(sysDict);
		sysDictItemService.removeByDictId(id);
		List<SysDictItemModifyDTO> sysDictItemList = sysDictModifyDTO.getSysDictItemList();
		if (CollUtil.isNotEmpty(sysDictItemList)) {
			List<SysDictItem> sysDictItems = SysDictItemConvert.INSTANCE.modifyDTOList2EntityList(sysDictItemList);
			sysDictItemService.saveBatchByDictId(id, sysDictItems);
		}
	}

	@Override
	public SysDictDetailVO detailById(Long id) {
		SysDict sysDict = this.getById(id);
		SysDictDetailVO sysDictDetailVO = SysDictConvert.INSTANCE.entity2DetailVO(sysDict);
		List<SysDictItem> sysDictItems = sysDictItemService.listByDictId(id);
		if (CollUtil.isNotEmpty(sysDictItems)) {
			sysDictDetailVO.setSysDictItemList(SysDictItemConvert.INSTANCE.entityList2BaseVOList(sysDictItems));
		}
		return sysDictDetailVO;
	}

	@Override
	public PageVO<SysDictPageVO> queryPage(SysDictPageDTO sysDictPageDTO) {
		Long page = sysDictPageDTO.getPage();
		Long size = sysDictPageDTO.getSize();
		Page<SysDict> sysDictPage = page(
				lambdaQuery()
						.orderByDesc(SysDict::getUpdatedAt)
						.page(Page.of(page, size))
		);
		List<SysDictPageVO> pageVOS = SysDictConvert.INSTANCE.entityList2PageVOList(sysDictPage.getRecords());
		return PageVO.of(sysDictPage, pageVOS);
	}

	@Override
	public List<SysDictListVO> queryList() {
		ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
		String dictListStr = valueOperations.get(SYS_DICT_LIST_CACHE_KEY);
		if (StrUtil.isNotBlank(dictListStr)) {
			return JSON.parseArray(dictListStr, SysDictListVO.class);
		}
		List<SysDict> sysDictList = list();
		List<Long> dictIds = sysDictList.stream().map(SysDict::getId).toList();
		Map<Long, List<SysDictItem>> dictIdMap = sysDictItemService.listMapsByDictIds(dictIds);
		List<SysDictListVO> sysDictListVOList = sysDictList.stream()
				.map(SysDictConvert.INSTANCE::entity2ListVO)
				.peek(item -> {
					List<SysDictItem> sysDictItems = dictIdMap.get(item.getId());
					item.setChildren(SysDictItemConvert.INSTANCE.entityList2ListVOList(sysDictItems));
				}).toList();
		valueOperations.set(SYS_DICT_LIST_CACHE_KEY, JSON.toJSONString(sysDictListVOList));
		return sysDictListVOList;
	}
}
